﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections.ObjectModel;
using SurfaceCardsBoardLibrary.Interfaces;
using SurfaceCardsBoardLibrary;
using Microsoft.Surface.Presentation.Controls;
using System.Windows.Shapes;
using System.Windows;
using System.Windows.Media.Imaging;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Controls.Primitives;
using Microsoft.Surface.Presentation;
using SurfaceCardsGameKit.Tools;
using System.Windows.Input;

namespace SurfaceCardsGameKit.Games.BasicGame
{
    public class BasicGame : Game
    {
        public BasicGame(Board board) :
            base(board)
        {
            CardWidth = 75;
            CardHeight = 106;

            DeckWidth = 130;
            DeckHeight = 150;

            this.GameBackground = Application.Current.FindResource("TapisJeuLibre") as DrawingBrush; 

            this.CardFrontBrushesCache = new Dictionary<BasicCardValue, ImageBrush>();

            var drawingBackBrush = Application.Current.FindResource("Dos") as DrawingBrush;
            BackCardsBrush = CreateImageBrushFromDrawingBrushForCard(drawingBackBrush);
            board.IsCollidePathEnabled = true;
            board.CollidePathBrush = Board.DefaultCollidePathColor;
        }

        #region Properties

        public Dictionary<BasicCardValue, ImageBrush> CardFrontBrushesCache { get; private set; }

        public Brush BackCardsBrush { get; private set; }

        #endregion

        #region Cards

        public void CreateBrushesFor52Cards()
        {
            for (int i = 1; i <= 4; i++)
            {
                for (int j = 1; j <= 13; j++)
                    GetFrontBrush(new BasicCardValue((BasicCardsNumber)j, (BasicCardsColor)i));
            }
        }

        public void Add52CardsToBoard()
        {
            for (int i = 1; i <= 4; i++)
            {
                for (int j = 1; j <= 13; j++)
                {
                    var cardValue = new BasicCardValue((BasicCardsNumber)j, (BasicCardsColor)i);

                    AddCard(cardValue);
                }
            }
        }

        public void ShuffleCardsPositions(IEnumerable<Card> cards)
        {
            Random rand = new Random();
            foreach (var card in cards)
            {
                card.Center = new Point(rand.NextDouble() * 1024, rand.NextDouble() * 768);
                card.Orientation = rand.NextDouble() * 360;
            }
        }

        public Card AddCard(BasicCardsNumber number, BasicCardsColor color)
        {
            return AddCard(new BasicCardValue(number, color));
        }

        public Card AddCard(BasicCardValue cardValue)
        {
            Card card = new Card()
            {
                CardValue = cardValue,
                FrontBackground = GetFrontBrush(cardValue),
                BackBackground = BackCardsBrush,
                IsFront = true,
                UseBackgroundOnlyForFlip = true,
                DefaultWidth = CardWidth,
                DefaultHeight = CardHeight,
            };

            base.AddCard(card);
            return card;
        }

        protected override void InitializeCard(Card card)
        {
            ScatterViewItem svi = _board.ScatterView.GetScatterViewItemForItem(card);
            svi.CanScale = false;

            base.InitializeCard(card);
        }


        #endregion

        #region Decks

        protected override void InitializeDeck(DeckWaitingInitialization deck)
        {
            base.InitializeDeck(deck);

            ScatterViewItem svi = _board.ScatterView.GetScatterViewItemForItem(deck.Deck);
            var uc = svi.Content as DeckUC;

            if (uc != null)
                uc.BackBackground = BackCardsBrush;
        }

        #endregion

        #region Commands

        private DelegateCommand _gatherCardsCommand;
        public override ICommand GatherCardsCommand
        {
            get
            {
                if (_gatherCardsCommand == null)
                {
                    _gatherCardsCommand = new DelegateCommand(
                    () => GatherCards());
                }
                return _gatherCardsCommand;
            }
        }

        private void GatherCards()
        {
            Deck allCards = this.CreateDeck();

            using (allCards.DeferUpdateDisposition(true, true))
            {
                foreach (var deck in this.Decks.ToList())
                {
                    var cards = deck.ToList();
                    this._board.RemoveCardsFromDeck(deck, cards);
                    this._board.AddCardsToDeck(allCards, cards);
                }

                foreach (Card card in Cards.OfType<Card>().Where(c => c.Deck != allCards))
                {
                    this._board.AddCardToDeck(allCards, card);
                }
            }
        }

        #endregion

        /// <summary>
        /// Creates an ImageBrush from a DrawingBrush, making card consuming less memory
        /// </summary>
        /// <param name="drawingBrush"></param>
        /// <returns></returns>
        public ImageBrush CreateImageBrushFromDrawingBrushForCard(DrawingBrush drawingBrush)
        {
            Rectangle R = new Rectangle { Fill = drawingBrush };

            R.Measure(new Size(CardWidth, CardHeight));
            R.Arrange(new Rect(new Size(CardWidth, CardHeight)));

            var bmp1 = new RenderTargetBitmap(Convert.ToInt32(CardWidth), Convert.ToInt32(CardHeight), 96, 96, PixelFormats.Pbgra32);
            bmp1.Render(R);

            return new ImageBrush(bmp1);
        }

        private ImageBrush GetFrontBrush(BasicCardValue cardvalue)
        {
            if (!this.CardFrontBrushesCache.ContainsKey(cardvalue))
            {
                var C = new ImageCard((int)cardvalue.Number) { Color = cardvalue.Color };

                C.Measure(new Size(CardWidth, CardHeight));
                C.Arrange(new Rect(new Size(CardWidth, CardHeight)));


                var bmp = new RenderTargetBitmap(Convert.ToInt32(C.ActualWidth), Convert.ToInt32(C.ActualHeight), 96, 96, PixelFormats.Pbgra32);
                bmp.Render(C);

                ImageBrush b = new ImageBrush(bmp);
                this.CardFrontBrushesCache[cardvalue] = b;

                return b;
            }
            else
            {
                return this.CardFrontBrushesCache[cardvalue];
            }
        }

    }
}
